#include <iostream>
#include <mutex>

using std::cout;
using std::endl;

template <class T>
class SharedPtr
{
public:
    /*
        构造函数
        调用构造函数的对象是资源的第1个持有者
        因此引用计数初始化为 1
    */
    SharedPtr(T *ptr = nullptr)
        : _ptr(ptr), _pRefCnt(new int(1)), _pmtx(new std::mutex)
    {
    }

    /*
        拷贝构造
        调用拷贝构造的对象是资源的第n个持有者
        需要拷贝之后让引用计数 + 1
    */
    SharedPtr(const SharedPtr<T> &sp)
        : _ptr(sp._ptr), _pRefCnt(sp._pRefCnt), _pmtx(sp._pmtx)
    {
        _AddRef();
    }
    /*引用计数++*/
    void _AddRef()
    {
        _pmtx->lock();
        ++(*_pRefCnt);
        _pmtx->unlock();
    }

    /*赋值重载*/
    SharedPtr<T> &operator=(const SharedPtr<T> &sp)
    {
        if (_ptr != sp._ptr) // 如果自己和sp的资源是一样的，就不用操作了
        {
            // 1.释放自己的资源
            _Release();
            // 2.拷贝对方的资源
            _ptr = sp._ptr;
            _pmtx = sp._pmtx;
            _pRefCnt = sp._pRefCnt;
            // 3.引用计数加一
            _AddRef();
        }
        return *this;
    }

    /*析构函数*/
    ~SharedPtr()
    {
        _Release();
    }
    /*根据引用计数的值决定是否释放资源*/
    void _Release()
    {
        _pmtx->lock();
        bool isRelease = false;
        if (--(*_pRefCnt) == 0 && _ptr)
        {
            delete _ptr;
            delete _pRefCnt;
            isRelease = true;
        }
        _pmtx->unlock();
        if (isRelease)
            delete _pmtx;
    }

public:
    int refCnt()
    {
        return *_pRefCnt;
    }
    T &operator*()
    {
        return *_ptr;
    }
    T *operator->()
    {
        return _ptr;
    }
    T *get() const
    {
        return _ptr;
    }

private:
    T *_ptr;           // 资源
    int *_pRefCnt;     // 引用计数
    std::mutex *_pmtx; // 保护引用计数的互斥锁
};


template <class T>
class weak_ptr
{
public:
    weak_ptr()
        : _ptr(nullptr)
    {
    }
    weak_ptr(const SharedPtr<T> &sp)
        : _ptr(sp.get())
    {
    }
    weak_ptr<T> &operator=(const SharedPtr<T> &sp)
    {
        _ptr = sp.get();
        return *this;
    }
    T &operator*()
    {
        return *_ptr;
    }
    T *operator->()
    {
        return _ptr;
    }

private:
    T *_ptr;
};


void testSharedPtr()
{
    SharedPtr<int> sp1(new int(4));
    std::cout << *sp1.get() << std::endl;

    auto sp2 = sp1;
    *sp2 = 2;
    std::cout << *sp1.get() << std::endl;

    SharedPtr<int> sp3;
    sp3 = sp2;
    *sp3 = 666;
    std::cout << *sp1.get() << std::endl;
}

struct ListNode
{
    int _data;
    weak_ptr<ListNode> _next;
    weak_ptr<ListNode> _prev;
};

void testWeakPtr()
{
    SharedPtr<ListNode> node1(new ListNode);
    SharedPtr<ListNode> node2(new ListNode);
    printf("node1的引用计数：%d\t", node1.refCnt());
    printf("node2的引用计数：%d\n", node2.refCnt());
    node1->_next = node2;
    node2->_prev = node1;
    printf("node1的引用计数：%d\t", node1.refCnt());
    printf("node2的引用计数：%d\n", node2.refCnt());
}